/*-*-C-*-
 *
 * Minimal dbox manipulation
 */

#include "resed.h"

/*
 * Set a string field to the given entry.  If the size is too big
 * for the icon's buffer, shorten it.  Pass "" to clear the
 * field.  The icon must be indirected.
 *
 * If the src and dst seem to be the same string, just update.
 */

error * dbox_setstring (WindowPtr win, int i, char *s)
{
    char *dst = (char *) win->icons[i].data[0];
    if (s != dst)
    {
        int len = strlen(s);
        if (len > win->icons[i].data[2] - 1)
            len = win->icons[i].data[2] - 1;
        strncpy(dst, s, len);
        *(dst + len) = 0;
    }
    
    /* If the icon has the caret, set it to the start of the string */
    block
    {
        CaretPositionRec caret;
        ER ( swi (Wimp_GetCaretPosition,  R1, &caret,  END) );
        if (caret.windowhandle == win->handle &&
            caret.iconhandle == i &&
            caret.height != -1)
        {
            ER ( swi (Wimp_SetCaretPosition,
                      R0, win->handle,  R1, i,
                      R2, caret.position.x,  R3, caret.position.y,  R4, -1,  R5, strlen(dst),  END ) );
        }
    }

    block
    {
        SetIconStateRec state;
        state.windowhandle = win->handle;
        state.iconhandle = i;
        state.clear = 0;
        state.eor = 0;
        ER ( swi (Wimp_SetIconState,  R1, &state,  END) );
    }
    return NULL;
}


error * dbox_setint (WindowPtr win, int i, int v)
{
    char buf[30];
    sprintf (buf, "%d", v);
    if (strlen(buf) < win->icons[i].data[2])
        return dbox_setstring (win, i, buf);
    else
        return NULL;
}


/*
 * Obtain pointer to text of the given field.
 */

char *dbox_getstring (WindowPtr win, int i)
{
    return (char *) win->icons[i].data[0];
}



/*
 * Turn a button on or off without checking for radio behaviour
 */

error * dbox_setbutton (WindowPtr win, int i, Bool on)
{
    SetIconStateRec state;
    state.windowhandle = win->handle;
    state.iconhandle = i;
    state.clear = IF_SELECTED;
    state.eor = on ? IF_SELECTED : 0;
    return swi (Wimp_SetIconState,  R1, &state,  END);
}

    

#if 0
/*
 * Turn a button on or off.  Check for others in the same non-zero ESG
 * and enforce radio behaviour.  (ie, you can have all buttons off,
 * but only one on.)
 */

void dbox_setbutton (WindowPtr win, int i, Bool on)
{
    int esg = IF_GET_FIELD(ESG, win->icons[i].flags);
    
    setbutton (win, i, on);

    if (esg)
    {
        int j;
        for (j = 0; j < win->numicons; j++)
        {
            int flags = win->icons[j].flags;
            if (i != j &&
                !(flags & IF_DELETED) &&
                IF_GET_FIELD(ESG, flags) == esg)
            setbutton (win, j, FALSE);
        }
    }
}
#endif

            
/*
 * Get the icon flags for an icon
 */

unsigned int dbox_getflags (WindowPtr win, int i)
{
    IconStateRec state;
    state.windowhandle = win->handle;
    state.iconhandle = i;
    swi (Wimp_GetIconState,  R1, &state,  END);
    return state.icon.flags;
}


/*
 * Get button status
 */

Bool dbox_getbutton (WindowPtr win, int i)
{
    return (dbox_getflags (win, i) & IF_SELECTED) != 0;
}


/*
 * Change icon flags for an icon.  Pass i == -1 to apply it to
 * all icons in the window.
 */

error * dbox_iconflag (WindowPtr win, int i, unsigned int clear, unsigned int eor)
{
    if (i == -1)
    {
        for (i = 0; i < win->numicons; i++)
            if ((dbox_getflags (win, i) & IF_DELETED) == 0)
            {
                ER ( dbox_iconflag (win, i, clear, eor) );
            }
    }
    else
    {
        SetIconStateRec state;
        state.windowhandle = win->handle;
        state.iconhandle = i;
        state.clear = clear;
        state.eor = eor;
        ER ( swi (Wimp_SetIconState,  R1, &state,  END) );
    }
    return NULL;
}


/*
 * Shade/unshade a single icon according to 'shaded'
 */

error * dbox_shade (WindowPtr win, int i, Bool shaded)
{
    unsigned int eor = shaded ? IF_SHADED : 0;
    return dbox_iconflag (win, i, IF_SHADED, eor);
}


